<template>
	<form :class="classes" :autocomplete="autocomplete">
		<slot></slot>
	</form>
</template>
<script lang="ts">
	import Anes from "../base";
	import {
		Prop,
		Emit,
		Component,
		Watch,
		Mixins,
		Provide
	} from "vue-property-decorator";
	import { oneOf, findComponentsDownward } from "../../utils/assist";
	import { Rules } from "async-validator";
	import FormItem from "./form-item.vue";
	import { formKey } from "../../utils/const";
	const prefixCls = "ivu-form";
	@Component
	export default class Form extends Mixins(Anes) {
		@Prop({
			type: String,
			default: "right",
			validator(value: string) {
				return oneOf(value, ["left", "right", "top"]);
			}
		})
		labelPosition!: string;
		@Prop({
			type: String,
			default: "off",
			validator(value: string) {
				return oneOf(value, ["on", "off"]);
			}
		})
		autocomplete!: string;
		@Prop(Object) model!: object;
		@Prop() rules!: Rules;
		@Prop(Number) labelWidth!: number;
		@Prop({ type: Boolean, default: false }) inline!: boolean;
		@Prop({ type: Boolean, default: true }) showMessage!: boolean;
		@Prop({ type: Boolean, default: false }) hideRequiredMark!: boolean;
		@Prop({ type: Boolean, default: false }) labelColon!: boolean;
		@Prop({ type: Boolean, default: false }) disabled!: boolean;

		fields = new Array<FormItem>();

		created() {
			this.$on("on-form-item-add", (field: FormItem) => {
				if (field) this.fields.push(field);
				return false;
			});
			this.$on("on-form-item-remove", (field: FormItem) => {
				if (field.prop) this.fields.splice(this.fields.indexOf(field), 1);
				return false;
			});
		}
		mounted() {
			this.fields = findComponentsDownward<FormItem>(this, "FormItem");
		}
		/* 	provide() {
						return { FormInstance: this };
					}
			 */
		get classes() {
			return [
				`${prefixCls}`,
				`${prefixCls}-label-${this.labelPosition}`,
				{
					[`${prefixCls}-inline`]: this.inline,
					[`${prefixCls}-hide-required-mark`]: this.hideRequiredMark
				}
			];
		}
		get colon() {
			let colon = "";
			if (this.labelColon) {
				colon = typeof this.labelColon === "boolean" ? ":" : this.labelColon;
			}
			return colon;
		}

		resetFields() {
			this.fields.forEach(field => {
				field.resetField();
			});
		}
		validate(callback?: Function) {
			return new Promise(resolve => {
				let valid = true;
				let count = 0;

				this.fields.forEach(field => {
					field.validate("", (errors: string) => {
						if (errors) {
							valid = false;
						}
						if (++count === this.fields.length) {
							// all finish
							resolve(valid);
							if (typeof callback === "function") {
								callback(valid);
							}
						}
					});
				});
			});
		}
		validateField(prop: string, cb: Function) {
			const field = this.fields.filter(field => field.prop === prop)[0];
			if (!field) {
				throw new Error(
					"[iView warn]: must call validateField with valid prop string!"
				);
			}

			field.validate("", cb);
		}
		@Watch("rules")
		onChangeValue() {
			this.validate();
		}
		/* @Provide(formKey)
		FormInstance = { key: "this is from parent" }; */
	}
</script>
